﻿using ExcelUnity.Core;
using ExcelUnity.Importer.Importers;
using ExcelUnity.Importer.Results;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExcelUnity.Importer.Wrappers
{
    public class SheetWrapper
    {
        public SheetWrapper(ImportBookSheet importSheet, int sheetIndex, string sheetName)
        {
            SheetIndex = sheetIndex;
            SheetName = sheetName;
            ImportSheet = importSheet;
            HeaderIndex = importSheet.HeaderRowIndex;
        }

        public ImportBookSheet ImportSheet { get; }

        /// <summary>
        /// sheet索引
        /// </summary>
        public int SheetIndex { get; }

        /// <summary>
        /// sheet名称
        /// </summary>
        public string SheetName { get; }

        /// <summary>
        /// header行所在索引
        /// </summary>
        public int? HeaderIndex { get; }

        /// <summary>
        /// 数据行开始索引
        /// </summary>
        public int? DataRowStartIndex { get; set; }

        /// <summary>
        /// 列名集合
        /// </summary>
        public List<ColumnWrapper>? Columns { get; set; }

        /// <summary>
        /// 数据行，不包括列名行
        /// </summary>
        public List<RowWrapper>? Rows { get; set; }

        /// <summary>
        /// 承载数据,list，或datatable或dictionary
        /// </summary>
        public object? ModelData { get; set; }

        /// <summary>
        /// sheet格式错误信息
        /// </summary>
        public string? SheetError { get; set; }

        /// <summary>
        /// 明细错误信息
        /// </summary>
        public string? DetailError { get; private set; }

        /// <summary>
        /// 唯一索引错误信息
        /// </summary>
        public string? UniqueError { get; private set; }

        /// <summary>
        /// 错误统计信息
        /// </summary>
        public string SummaryError => string.Concat(SheetError, DetailError, UniqueError);

        /// <summary>
        /// 错误行
        /// </summary>
        public List<RowWrapper>? ErrorRows { get; private set; }

        /// <summary>
        /// 重复行
        /// </summary>
        public List<List<RepeatRow>>? RepeatRowIndexes { get; private set; }

        /// <summary>
        /// 当前sheet是否校验成功
        /// </summary>
        public bool IsValidated => SummaryError.IsNullOrWhiteSpace();

        /// <summary>
        /// 所有的错误行索引
        /// </summary>
        public List<int> ErrorRowIndexes { get; private set; } = new List<int>();

        public bool Validate()
        {
            UniqueError = BuildUniqueError();

            DetailError = BuildDetailError();

            if (ModelData == null) return IsValidated;

            ErrorRowIndexes = new List<int>();
            if (ErrorRows.IsNotNullOrEmpty())
                ErrorRowIndexes.AddRange(ErrorRows.Select(x => x.RowIndex));
            if (RepeatRowIndexes.IsNotNullOrEmpty())
                ErrorRowIndexes.AddRange(RepeatRowIndexes.SelectMany(x => x.Select(y => y.RowIndex)));
            ErrorRowIndexes = ErrorRowIndexes.Distinct().ToList();

            if (Rows.IsNotNullOrEmpty() && ImportSheet.ValidateHandler != null)
            {
                ImportSheet.ValidateHandler.Invoke(this, ModelData);
                DetailError = BuildDetailError();
            }
            return IsValidated;
        }

        private string? BuildUniqueError()
        {
            if (!ImportSheet.NeedUniqueValidation) return null;

            if (Rows.IsNullOrEmpty()) return null;

            RepeatRowIndexes = Rows.GroupBy(m => m.UniqueSign)
                                    .Where(m => m.Count() > 1)
                                    .Select(m => m.Select(p => new RepeatRow(p.RowIndex, p.Cells.Where(x => x.IsUnique).Select(x => x.ColumnIndex).ToList())).ToList())
                                    .ToList();

            if (RepeatRowIndexes.IsNullOrEmpty()) return null;

            var msg = new StringBuilder();
            RepeatRowIndexes.ForEach(item =>
            {
                msg.Append($"第{string.Join(",", item.Select(m => m.DisplayRowIndex))}行.{ImportSheet.UniqueValidationPrompt}.{Environment.NewLine}");
            });
            return msg.ToString();
        }

        private string? BuildDetailError()
        {
            ErrorRows = Rows?.Where(p => !p.IsValidated).ToList();

            if (ErrorRows.IsNullOrEmpty()) return null;

            var errMsg = new StringBuilder();
            foreach (var item in ErrorRows!)
            {
                foreach (var cell in item.Cells.Where(x => x.Error.IsNotNullOrWhiteSpace()))
                    errMsg.Append($"第{item.RowIndex + 1}行{cell.ColumnIndex + 1}列,{cell.Error}.{Environment.NewLine}");
            }
            return errMsg.ToString();
        }

        /// <summary>
        /// 单条数据是否校验成功
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool IsValidatedData(object data)
        {
            var sheetRow = Rows.FirstOrDefault(x => x.ModelData == data);
            if (sheetRow == null) return false;

            return sheetRow.IsValidated;
        }

        public bool SetError(object data, string propertyName, string? errorMsg = null)
        {
            var sheetRow = Rows.FirstOrDefault(x => x.ModelData == data);
            if (sheetRow == null) return false;

            if (sheetRow.Cells.IsNullOrEmpty()) return false;

            if (errorMsg.IsNullOrWhiteSpace()) errorMsg = "数据错误";

            var cell = sheetRow.Cells.FirstOrDefault(x => x.PropertyName == propertyName);
            if (cell == null) return false;

            cell.AppendError(errorMsg!);
            return true;
        }

        public bool SetError(object data, int columnIndex, string? errorMsg = null)
        {
            var sheetRow = Rows.FirstOrDefault(x => x.ModelData == data);
            if (sheetRow == null) return false;

            if (sheetRow.Cells.IsNullOrEmpty()) return false;

            if (errorMsg.IsNullOrWhiteSpace()) errorMsg = "数据错误";

            var cell = sheetRow.Cells.FirstOrDefault(x => x.ColumnIndex == columnIndex);
            if (cell == null) return false;

            cell.AppendError(errorMsg!);
            return true;
        }

        public ResultSheet ToResultSheet()
        {
            return new ResultSheet(SheetIndex, SheetName, IsValidated, SheetError, SummaryError, ModelData);
        }
        public CsvResultSheet ToCsvResultSheet()
        {
            return new CsvResultSheet(IsValidated, SheetError, SummaryError, ModelData);
        }
    }
}
